package com.songlanyun.common.utils.push;

import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.getui.push.v2.sdk.ApiHelper;
import com.getui.push.v2.sdk.api.PushApi;
import com.getui.push.v2.sdk.api.UserApi;
import com.getui.push.v2.sdk.common.ApiResult;
import com.getui.push.v2.sdk.dto.req.Audience;
import com.getui.push.v2.sdk.dto.req.AudienceDTO;
import com.getui.push.v2.sdk.dto.req.Settings;
import com.getui.push.v2.sdk.dto.req.Strategy;
import com.getui.push.v2.sdk.dto.req.message.PushChannel;
import com.getui.push.v2.sdk.dto.req.message.PushDTO;
import com.getui.push.v2.sdk.dto.req.message.PushMessage;
import com.getui.push.v2.sdk.dto.req.message.android.AndroidDTO;
import com.getui.push.v2.sdk.dto.req.message.android.ThirdNotification;
import com.getui.push.v2.sdk.dto.req.message.android.Ups;
import com.getui.push.v2.sdk.dto.req.message.ios.Alert;
import com.getui.push.v2.sdk.dto.req.message.ios.Aps;
import com.getui.push.v2.sdk.dto.req.message.ios.IosDTO;
import com.getui.push.v2.sdk.dto.res.CidStatusDTO;
import com.getui.push.v2.sdk.dto.res.TaskIdDTO;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.songlanyun.common.utils.RedisKeys;
import com.songlanyun.common.utils.RedisUtils;
import com.songlanyun.common.utils.custom.ClassConvertUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author wuchao
 */
@Slf4j
@Component
public class GeTuiUtils {

    private PushApi pushApi;
    private UserApi userApi;

    public GeTuiUtils(ApiHelper apiHelper) {
        pushApi = apiHelper.creatApi(PushApi.class);
        userApi = apiHelper.creatApi(UserApi.class);
    }

    @Resource
    private RedisUtils redisUtils;

    public boolean pushToSingleByCid(Msg msg) {
        PushDTO<Audience> pushDTO = this.buildPushDTO(msg);
        // 设置接收人信息
        Audience audience = new Audience();
        pushDTO.setAudience(audience);
        audience.addCid(msg.getCid());// cid
        // 进行cid单推
        ApiResult<Map<String, Map<String, String>>> apiResult = pushApi.pushToSingleByCid(pushDTO);
        //successed_offline: 离线下发(包含厂商通道下发)，successed_online: 在线下发，successed_ignore: 最近90天内不活跃用户不下发
        log.info(String.format("单推[%s]，返回结果：%s", apiResult.getMsg(), apiResult.getData()));
        return apiResult.isSuccess();
    }

    /**
     * cid批量推
     *
     * @param msg
     */
    public boolean pushListByCid(Msg msg) {
        //批量发送
        AudienceDTO audienceDTO = new AudienceDTO();
        PushDTO<Audience> pushDTO = this.buildPushDTO(msg);

        ApiResult<TaskIdDTO> createApiResult = pushApi.createMsg(pushDTO);
        if (!createApiResult.isSuccess()) {
            log.error("推送：创建消息失败：" + createApiResult.getMsg());
            return false;
        }
        // 设置接收人信息
        Audience audience = new Audience();
        pushDTO.setAudience(audience);
        audience.setCid(msg.getCidList());

        audienceDTO.setAudience(audience);
        audienceDTO.setTaskid(createApiResult.getData().getTaskId());
        audienceDTO.setAsync(true);

        ApiResult<Map<String, Map<String, String>>> apiResult = pushApi.pushListByCid(audienceDTO);
        log.info(String.format("批量推[%s]，返回结果：%s", apiResult.getMsg(), apiResult.getData()));
        return apiResult.isSuccess();
    }

    private PushDTO<Audience> buildPushDTO(Msg msg) {
        PushDTO<Audience> pushDTO = new PushDTO<>();
        //前端接收的消息
        Map<String, Object> map = new HashMap<>();
        map.put("title", msg.getTitle());
        map.put("content", msg.getContent());
        map.put("payload", msg.getMsg());
        String payload = ClassConvertUtils.transformJSONToSnake(map);

        // 设置推送参数
        //requestid需要每次变化唯一
        pushDTO.setRequestId(System.currentTimeMillis() + "");
        pushDTO.setGroupName("wxb-group");

        //配置推送条件
        // 1: 表示该消息在用户在线时推送个推通道，用户离线时推送厂商通道;
        // 2: 表示该消息只通过厂商通道策略下发，不考虑用户是否在线;
        // 3: 表示该消息只通过个推通道下发，不考虑用户是否在线；
        // 4: 表示该消息优先从厂商通道下发，若消息内容在厂商通道代发失败后会从个推通道下发。
        Strategy strategy = new Strategy();
        strategy.setDef(1);
        strategy.setSt(1);
        Settings settings = new Settings();
        settings.setStrategy(strategy);
        pushDTO.setSettings(settings);
        //消息有效期，走厂商消息需要设置该值
        settings.setTtl(3600000);

        //推送苹果离线通知标题内容
        Alert alert = new Alert();
        //苹果离线通知栏标题
        alert.setTitle(msg.getTitle());
        //苹果离线通知栏内容
        alert.setBody(msg.getContent());
        Aps aps = new Aps();
        //1表示静默推送(无通知栏消息)，静默推送时不需要填写其他参数。
        //苹果建议1小时最多推送3条静默消息
        aps.setContentAvailable(0);
        aps.setSound("default");
        aps.setAlert(alert);
        IosDTO iosDTO = new IosDTO();
        iosDTO.setAps(aps);
        iosDTO.setType("notify");
        iosDTO.setPayload(payload);
        PushChannel pushChannel = new PushChannel();
        pushChannel.setIos(iosDTO);
        //安卓离线厂商通道推送消息体
        AndroidDTO androidDTO = new AndroidDTO();
        Ups ups = new Ups();
        ThirdNotification notification1 = new ThirdNotification();
        ups.setNotification(notification1);
        //安卓离线展示的标题
        notification1.setTitle(msg.getTitle());
        //安卓离线展示的内容
        notification1.setBody(msg.getContent());
        notification1.setClickType("intent");
        notification1.setIntent("intent:#Intent;action=android.intent.action.oppopush;launchFlags=0x14000000;component=com.weixiaobao/io.dcloud.PandoraEntry;S.UP-OL-SU=true;S.title=" + msg.getTitle() + ";S.content=" + msg.getContent() + ";S.payload=" + msg.getMsg() + ";end");
        //各厂商自有功能单项设置
        //ups.addOption("HW", "/message/android/notification/badge/class", "io.dcloud.PandoraEntry ");
        //ups.addOption("HW", "/message/android/notification/badge/add_num", 1);
        //ups.addOption("HW", "/message/android/notification/importance", "HIGH");
        //ups.addOption("VV","classification",1);
        androidDTO.setUps(ups);
        pushChannel.setAndroid(androidDTO);
        pushDTO.setPushChannel(pushChannel);

        // PushMessage在线走个推通道才会起作用的消息体
        PushMessage pushMessage = new PushMessage();
        pushDTO.setPushMessage(pushMessage);
        pushMessage.setTransmission(payload);
        return pushDTO;
    }

    /**
     * 单推
     *
     * @param msg
     * @return
     */
    public void pushByUserId(Msg msg) {
        try {
            if (ObjectUtils.isEmpty(msg.getUid())) {
                log.error("用户ID不能为空");
                return;
            }
            //获取Push客户端ID：6a67d611f29e233492223e2de4d7a0c7
            String clientId = redisUtils.get(RedisKeys.getPushCid(String.valueOf(msg.getUid())));
            if (StringUtils.isEmpty(clientId)) {
                log.error("客户端ID没有获取到");
                return;
            }
            msg.setCid(clientId);
            //单推
            this.pushToSingleByCid(msg);
        } catch (Exception e) {
            log.error("单推异常");
        }
    }

    /**
     * 批量推
     *
     * @param msg
     * @return
     */
    public void pushByUserIds(Msg msg) {
        try {
            if (CollectionUtils.isEmpty(msg.getUidList())) {
                log.error("用户ID不能为空");
                return;
            }
            List<String> cidList = new ArrayList<>();
            msg.getUidList().forEach(u -> {
                //获取Push客户端ID：6a67d611f29e233492223e2de4d7a0c7
                String clientId = redisUtils.get(RedisKeys.getPushCid(String.valueOf(u)));
                //去重
                if (!StringUtils.isEmpty(clientId) && !cidList.contains(clientId)) {
                    cidList.add(clientId);
                }
            });

            if (CollectionUtils.isEmpty(cidList)) {
                log.error("客户端ID没有获取到");
                return;
            }

            if (cidList.size() > 200) {
                //按每200个一组分割
                List<List<String>> parts = Lists.partition(cidList, 200);
                parts.forEach(list -> {
                    msg.setCidList(list);
                    //批量推
                    this.pushListByCid(msg);
                });
            }

        } catch (Exception e) {
            log.error("批量推异常");
        }
    }

    /**
     * 查询用户状态
     *
     * @param cid 客户端标识
     */
    public void queryUserStatus(String cid) {
        ApiResult<Map<String, CidStatusDTO>> mapApiResult = userApi.queryUserStatus(Sets.newHashSet(cid));
        log.info(String.format("用户状态：%s", mapApiResult));//online在线 offline离线
    }

}
